(function () {
    "use strict";

    var longurlplease = {
        shortUrlPattern : null,
        shortUrlRegexp : null,
        expandMethod : null,
        numberOfShortUrlsPerRequest : 4,
        onLoad : function () {
            longurlplease.shortUrlPattern = longurlplease.getPrefs().getCharPref("shortUrlPattern");
            longurlplease.refreshServiceList();
            var appcontent = document.getElementById("appcontent");   // browser
            if (appcontent)
                appcontent.addEventListener("DOMContentLoaded", longurlplease.onPageLoad, true);
        },
        refreshServiceList : function () {
            var req = new XMLHttpRequest();
            req.open('GET', 'http://www.longurlplease.com/api/supported-services.json', true);
            req.onreadystatechange = function (aEvt) {
                if (req.readyState == 4) {
                    if (req.status == 200) {
                        var jsonResp = longurlplease.safeEvalJson(req.responseText);
                        longurlplease.getPrefs().setCharPref("shortUrlPattern", jsonResp['regex']);
                        longurlplease.shortUrlPattern = jsonResp['regex'];
                        longurlplease.shortUrlRegexp = new RegExp(longurlplease.shortUrlPattern);
                    }
                }
            };
            req.send(null);
        },
        onLongUrlPleaseDotCom : function (doc) {
            if (doc.getElementById('firefox')) {
                if (doc.getElementById('firefox').href.match(/0\.5\.1/)) {
                    doc.getElementById('firefox').innerHTML = 'Firefox Extension Installed';
                } else {
                    doc.getElementById('firefox').innerHTML = 'Upgrade Firefox Extension';
                }
            }
        },
        getPrefs : function () {
            return Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("extensions.longurlplease.");
        },
        onPageLoad : function (aEvent) {
            var eventDocument = aEvent.originalTarget;
            if (longurlplease.getPrefs().getBoolPref("expandenabled")) {
                longurlplease.loadExpandMethod();
                if (/^http:\/\/www.longurlplease.com.*/.test(eventDocument.location.href)) {
                    longurlplease.onLongUrlPleaseDotCom(eventDocument);
                } else if (!longurlplease.shortUrlRegexp.test(eventDocument.location.href)) {
                    longurlplease.expandShortUrls(eventDocument);
                }
            }
        },
        expandShortUrls : function (eventDocument) {
            var allLinks = eventDocument.getElementsByTagName('a');
            var currentLink;
            var toLengthen = [];
            var mapToDom = {};
            for (var i = 0; i < allLinks.length; i++) {
                currentLink = allLinks[i];
                if (currentLink.href.match(longurlplease.shortUrlRegexp)) {
                    toLengthen.push(currentLink.href);
                    var listOfLinks = mapToDom[currentLink.href];
                    if (listOfLinks == null) {
                        listOfLinks = [];
                    }
                    listOfLinks.push(currentLink);
                    mapToDom[currentLink.href] = listOfLinks;
                }
            }
            longurlplease.eachInGroups(longurlplease.numberOfShortUrlsPerRequest, toLengthen, function (urls) {
                longurlplease.replaceUsingLongUrlPleaseAPI(mapToDom, urls, eventDocument);
            });
        },
        eachInGroups : function (numInGroup, arr, block) {
            var subArray, i = 0;
            while (i < arr.length) {
                subArray = arr.slice(i, i + numInGroup);
                block(subArray);
                i = i + numInGroup;
            }
        },
        createQueryString : function (urls) {
            var queryString = '';
            for (var i = 0; i < urls.length; i++) {
                queryString += (i > 0 ? '&q=' : 'q=');
                queryString += encodeURI(urls[i]);
            }
            return queryString;
        },
        loadExpandMethod : function () {
            var setting = longurlplease.getPrefs().getCharPref("expandstyle");
            if (setting == 'full')
                longurlplease.expandMethod = longurlplease.expandFull;
            else if (setting == 'href-only')
                longurlplease.expandMethod = longurlplease.expandHrefOnly;
            else if (setting == 'text-and-title')
                longurlplease.expandMethod = longurlplease.expandTextAndTitle;
            else
                longurlplease.expandMethod = longurlplease.expandSmart;
        },
        expandSmart : function (aTag, longUrl) {
            if (aTag.href == aTag.innerHTML) {
                var linkText = longUrl.replace(/^http(s?):\/\//, '').replace(/^www\./, '');
                aTag.innerHTML = linkText.substring(0, aTag.innerHTML.length - 3) + '...';
            }
            aTag.href = longUrl;
        },
        expandFull : function (aTag, longUrl) {
            aTag.href = longUrl;
            aTag.innerHTML = longUrl;
        },
        expandHrefOnly : function (aTag, longUrl) {
            aTag.href = longUrl;
        },
        expandTextAndTitle : function (aTag, longUrl) {
            var linkText = longUrl.replace(/^http(s?):\/\//, '').replace(/^www\./, '');
            aTag.innerHTML = linkText.substring(0, aTag.innerHTML.length - 3) + '...';
            aTag.title = longUrl;
        },
        replaceUsingLongUrlPleaseAPI : function (mapToDom, urls, eventDocument) {
            var req = new XMLHttpRequest();
            req.open('GET', 'http://www.longurlplease.com/api/v1.1?ua=ff0.5.1&' + longurlplease.createQueryString(urls), true);
            req.setRequestHeader('Referer', eventDocument.location.href);
            req.onreadystatechange = function (aEvt) {
                if (req.readyState == 4) {
                    if (req.status == 200) {
                        var jsonResp = longurlplease.safeEvalJson(req.responseText);
                        for (var k in jsonResp) {
                            var aTags = mapToDom[k];
                            if (jsonResp[k] != null) {
                                for (var ai = 0; ai < aTags.length; ai++) {
                                    var aTag = aTags[ai];
                                    longurlplease.expandMethod(aTag, jsonResp[k]);
                                }
                            }
                        }
                    }
                }
            };
            req.send(null);
        },
        safeEvalJson : function (string) {
            var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
            var versionChecker = Components.classes["@mozilla.org/xpcom/version-comparator;1"].getService(Components.interfaces.nsIVersionComparator);
            if (versionChecker.compare(appInfo.version, "3.0") >= 0)
                return longurlplease.jsonEval3(string);
            else
                return  longurlplease.jsonEval2(string);
        },
        jsonEval3 : function (string) {
            var nativeJSON = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
            return nativeJSON.decode(string);
        },
        jsonEval2 : function (string) {
            const maybeHarmful = /[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/;
            const jsonStrings = /"(\\.|[^"\\\n\r])*"/g;
            if (maybeHarmful.test(string.replace(jsonStrings, "")))
                return {};
            var s = new Components.utils.Sandbox("about:blank");
            return Components.utils.evalInSandbox("(" + string + ")", s);
        },
        logToConsole : function (msg) {
            var consoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
            consoleService.logStringMessage("@longer" + msg);
        }
    };
    window.addEventListener("load", function (e) {
        longurlplease.onLoad(e);
    }, false);
})();


